/*******************************************************************************
 * Copyright (c) 2012 Clever Devices.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v3.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/gpl.html
 * 
 * Contributors:
 * 	Clever Devices Interns - 
 * 	Alex Frankel, Andria Young, Kevin Thomas, Nicholas Culpepper, Taner Oztimurlenk, Thomas Volberg
 ******************************************************************************/
package com.framework.cleverstop_tentative;

//import com.google.android.maps.MapActivity;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import com.framework.beans.Bus;
import com.framework.beans.BusTimeRouteOverlay;
import com.framework.beans.Route;
import com.framework.bustime.ArrivalsGrid;
import com.framework.bustime_parser.ApiHandler;
import com.framework.bustime_parser.BusTimeItemizedOverlay;
import com.framework.bustime_parser.XMLParser;
import com.framework.fares.FarePaymentActivity;
import com.framework.menu.MenuAdapter;
import com.framework.menu.MenuItem;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;
import com.google.android.maps.Projection;
import com.slidingmenu.lib.app.SlidingMapActivity;

import android.app.ActionBar;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

/**
 * Main menu for the app after initial setup screen.  Pulls route information from the
 * BusTime API.  Can display buses and route pattern for selected route.  This should mimic
 * funtionality of the map on any given bustime website
 * 
 * @author AFrankel
 *
 */
public class BusTimeMainActivity extends SlidingMapActivity implements
		OnItemClickListener, OnClickListener, OnItemSelectedListener {

	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		ah = new ApiHandler();

		// sets main view
		setContentView(R.layout.bustime_main);
		setSlidingMenu();

		Drawable d = this.getResources().getDrawable(
				R.drawable.layout_background);
		ActionBar ab = getActionBar();
		ab.setBackgroundDrawable(d);
		ab.setHomeButtonEnabled(true);
		// set custom view here
		// ab.setCustomView(R.menu.options);
		// ab.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM |
		// ActionBar.DISPLAY_USE_LOGO);

		// setBehindContentView(R.layout.persistent_menu_list);

		mv = (MapView) findViewById(R.id.mapview);
		mv.setBuiltInZoomControls(true);
		mc = mv.getController();

		chicago = new GeoPoint(41850000, -87650000);

		mc.animateTo(chicago); // centers map around
								// city of chicago,
								// eventually will
								// center around
								// selected city
		mc.setZoom(12);

		routesList = (Spinner) findViewById(R.id.routeSpinner);

		routes = getRoutes();
		// pd.dismiss();
		routes.add(0, new Route("Not Used", "(Select Route)"));
		ArrayAdapter<Route> adapter = new ArrayAdapter<Route>(this,
				android.R.layout.simple_spinner_dropdown_item, routes);
		routesList.setAdapter(adapter);

		routesList.setOnItemSelectedListener(this);

		displayedRoutes = new ArrayList<String>();
	}
	
	//opens the sliding menu.  This was to make it known to the user that this
	//menu exists and is the core navigation of the app
	@Override
	protected void onResume() {
		// TODO Auto-generated method stub
		super.onResume();
		toggle();
	}

	@Override
	protected boolean isRouteDisplayed() {
		// TODO Auto-generated method stub
		return false;
	}

	/**
	 * Sets the sliding pullout menu for this activity.  Wanted to make this a static method, but
	 * was unable to for various reasons.  As a result, if you want to include this sliding menu (which you
	 * do!) this method as well as the onItemClick method must be copied (or MainMenu must be extended)
	 * 
	 * NFC ACTIVITY simulates an NFC tag being read if an NFC incapable device is used. 
	 */
	public void setSlidingMenu() {
		// sets view that slides out from left, this will be standard across all
		// menus
		// allowing for quick and intuitive navigation
		setBehindContentView(R.layout.persistent_menu_list);

		MenuItem[] menuItems = {
				new MenuItem("Rewards", R.drawable.rewaredsicon, "1"),
				new MenuItem("Cust. Service", R.drawable.boardsicon, ""),
				new MenuItem("Fares", R.drawable.faresicon, ""),
				new MenuItem("BusTime", R.drawable.bustimeicon, ""),
				new MenuItem("Arrivals", R.drawable.bus_menu, ""),
				new MenuItem("Alerts", R.drawable.alert, ""),
				new MenuItem("Settings", R.drawable.settinsicon, "") ,
				new MenuItem("NFC ACTIVITY", R.drawable.settinsicon, "")};

		ArrayList<MenuItem> items = new ArrayList<MenuItem>();
		for (int i = 0; i < menuItems.length; i++)
			items.add(menuItems[i]);

		String[] listItems = { "Rewards", "Boards", "Fares", "BusTime" };
		ArrayList<String> list = new ArrayList<String>();
		list.addAll(Arrays.asList(listItems));
		/*
		 * listData = new ArrayAdapter<String>(this,
		 * R.layout.slider_pullout_row, list);
		 */
		listData = new MenuAdapter(this, R.layout.listview_item_row, items);

		mainList = (ListView) findViewById(R.id.menuList);

		// dynamically add items to listView
		// did below as a test, but can easily add items based on the section of
		// app you are in
		// listData.insert("BusTime", list.size());

		mainList.setAdapter(listData);
		mainList.setOnItemClickListener(this);

		getSlidingMenu().setBehindOffsetRes(R.dimen.DistanceFromSide);
		getSlidingMenu().setBehindScrollScale(0.5f);
		// getSlidingMenu().setAboveTouchMode(SlidingMenu.TOUCHMODE_MARGIN);
		// getSlidingMenu().setBehindTouchMode(SlidingMenu.TOUCHMODE_FULLSCREEN);
		getSlidingMenu().setActivated(true);

	}

	@Override
	public void onItemClick(AdapterView<?> parent, View view, int index, long id) {
		// TODO Auto-generated method stub
		switch (index) {

		// this is where each intent will be started for all of your
		// respective sections. Look to the "BUSTIME" case as a model
		case REWARDS:
			Intent Rewards = new Intent("com.framework.rewards.REWARDS");
			startActivity(Rewards);
			break;
		case BOARDS:
			Intent Boards = new Intent("com.framework.customerservice.CUSTOMER");
			startActivity(Boards);
			break;
		case FARES:
			Intent Fares = new Intent("com.framework.cleverstop_tentative.FARESMAINACTIVITY");
			startActivity(Fares);
			break;
		case BUSTIME:
			Intent BusTime = new Intent(
					"com.framework.cleverstop_tentative.BUSTIMEMAINACTIVITY");
			startActivity(BusTime);
			break;
		case ALERTS:

			break;
		case ARRIVALS:
			Intent arrivals = new Intent(BusTimeMainActivity.this,
					ArrivalsGrid.class);
			startActivity(arrivals);
			break;
		case 7:
			Intent nfc = new Intent(BusTimeMainActivity.this,FarePaymentActivity.class);
			startActivity(nfc);
			break;
		}
	}

	/**
	 * Calls method from APIHandler to get list of routes for TA. This data populates
	 * the spinner in the onCreate method
	 * 
	 * @return
	 */
	public synchronized ArrayList<Route> getRoutes() {
		Thread background = new Thread() {
			public synchronized void run() {
				try {
					String xml = ah.getXML(ApiHandler.GET_ROUTES);
					routes = ah.getRoutes(xml);
					loading = false;
					// notifyAll();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		};
		background.start();

		ProgressDialog pDialog = ProgressDialog.show(BusTimeMainActivity.this,
				"", "Loading Routes...");

		while (loading) {
			try {
				wait(500);
				System.out.println("Loading Routes");
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		pDialog.dismiss();
		// REALLY shitty programming
		// this is just so that the while(loading) statement works as designed
		// if you have questions -- AF wrote this
		loading = true;

		return routes;
	}

	/**
	 * Displays the buses on the map for a given route.  Uses APIHandler method getBusesForRoute()
	 * 
	 * @param routeID route to retrieve buses for.  This is added to the BUSES_FOR_ROUTE_URL string
	 */
	public synchronized void displayBusesForRoute(final String routeID) {

		Thread background = new Thread() {

			public synchronized void run() {
				try {
					String xml = ah.getXML(ApiHandler.BUSES_FOR_ROUTE_URL
							+ routeID);
					busList = ah.getBusesForRoute(xml);
					loading = false;
					// notifyAll();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		};
		background.start();

		// ProgressDialog pDialog =
		// ProgressDialog.show(BusTimeMainActivity.this, "",
		// "Loading Route...",true);
		while (loading) {
			try {
				wait(500);
				System.out.println("Loading Buses");
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		// pDialog.dismiss();

		Toast.makeText(getApplicationContext(), "Route Loaded",
				Toast.LENGTH_SHORT).show();
		List<Overlay> mapOverlays = mv.getOverlays();
		
		//different color for each bus, probably a more efficient way of doing this.
		switch (Integer.parseInt(routeID)) {
		case 3:
			mapOverlayImage = this.getResources().getDrawable(
					R.drawable.bus_blue);
			break;
		case 4:
			mapOverlayImage = this.getResources().getDrawable(
					R.drawable.bus_green);
			break;
		case 8:
			mapOverlayImage = this.getResources().getDrawable(
					R.drawable.bus_purple);
			break;
		case 20:
			mapOverlayImage = this.getResources().getDrawable(
					R.drawable.bus_orange);
			break;
		case 49:
			mapOverlayImage = this.getResources().getDrawable(
					R.drawable.bus_red);
			break;
		default:
			// should never be called
			mapOverlayImage = this.getResources().getDrawable(
					R.drawable.small_bus);

		}
		BusTimeItemizedOverlay itemizedOverlay = new BusTimeItemizedOverlay(
				mapOverlayImage, this);

		for (int i = 0; i < busList.size(); i++) {
			point = new GeoPoint(busList.get(i).getBus()[1], busList.get(i)
					.getBus()[2]);
			OverlayItem overlayitem = new OverlayItem(point,
					String.valueOf(busList.get(i).getBus()[0]), busList.get(i)
							.getDest());
			itemizedOverlay.addOverlay(overlayitem);
		}
		itemizedOverlay.populateNow();
		mapOverlays.add(itemizedOverlay);

		mc.animateTo(chicago);

		// this is REALLY, REALLY shitty programming
		loading = true;
	}

	
	/**
	 * Displays the pattern of the route on the map as a line. No color customization
	 * 
	 * @param route
	 */
	public synchronized void displayRoute(final String route) {
		Thread background = new Thread() {
			public synchronized void run() {
				try {

					System.out.println(ApiHandler.GET_PATTERNS + route);
					String xml = ah.getXML(ApiHandler.GET_PATTERNS + route);
					geoList = ah.getPatterns(xml);
					loading = false;
					// notifyAll();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		};
		loading = true;
		background.start();

		while (loading) {
			try {
				wait(500);
				System.out.println("Loading Patterns");
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		loading = true;
		List<Overlay> mOverlays = mv.getOverlays();
		Projection projection = mv.getProjection();
		mOverlays.add(new BusTimeRouteOverlay(projection, geoList));

	}

	@Override
	public void onClick(View view) {
		switch (view.getId()) {
		}
	}

	@Override
	public void onItemSelected(AdapterView<?> parent, View view, int index,
			long id) {
		if (routesList.getSelectedItemPosition() == 0) {
			mv.getOverlays().clear();
			return;
		}

		Toast.makeText(getApplicationContext(), "Loading Route...",
				Toast.LENGTH_LONG).show();

		// clear all overlays then add all again with addition of new item
		displayedRoutes.add(((Route) routesList.getSelectedItem()).getId());
		mv.getOverlays().clear();

		// draws the route on the map
		displayRoute(((Route) routesList.getSelectedItem()).getId());

		// populates the route with buses
		for (int i = 0; i < displayedRoutes.size(); i++)
			displayBusesForRoute(displayedRoutes.get(i));

	}

	@Override
	public void onNothingSelected(AdapterView<?> arg0) {
		// TODO Auto-generated method stub

	}

	/**
	 * Attempted to create a refresh cycle so that the buses would "move", unsuccessful
	 */
	public void refresh() {
		// mv.getOverlays().clear();
		// for (int i = 0; i < displayedRoutes.size(); i++)
		// displayBusesForRoute(displayedRoutes.get(i));
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.options, menu);
		
		//actionBarRoutes = (Spinner) findViewById(R.id.busTimeRouteSpinner);
		//actionBarRoutes.setOnItemSelectedListener(this);
		
		
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(android.view.MenuItem item) {
		switch (item.getItemId()) {
		case android.R.id.home:
			toggle();
			return true;
		case R.id.btRouteSpinner:
			//displays the list of routes
			//routesList is a 0dp x 0dp spinner (formatting issue)
			routesList.performClick();
		default:
			return super.onOptionsItemSelected(item);
		}

	}

	ListView mainList;
	MenuAdapter listData;
	ListAdapter realListData;

	MapView mv;
	MapController mc;
	GeoPoint point;

	Button loadRoutes;
	Spinner routesList;
	Spinner actionBarRoutes;

	boolean loading = true;

	ArrayList<Bus> busList;
	ArrayList<Route> routes;
	ArrayList<GeoPoint> geoList;

	ApiHandler ah;

	ArrayList<String> displayedRoutes;

	Drawable mapOverlayImage;

	public final int REWARDS = 0;
	public final int BOARDS = 1;
	public final int FARES = 2;
	public final int BUSTIME = 3;
	public final int ARRIVALS = 4;
	public final int ALERTS = 5;

	ProgressDialog pd;

	GeoPoint chicago;

}
